package com.qsl.hook.utils;

import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import oshi.SystemInfo;
import oshi.software.os.OSProcess;
import oshi.software.os.OperatingSystem;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * 进程工具类
 */
public class ProcessUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(ProcessUtil.class);
    private static final int NULL_PROCESS_ID = -1;

    /**
     * 获取进程ID
     * @param process 进程
     * @return 进程id，-1表示获取失败
     * @author 青石路
     */
    public static int getProcessId(Process process) {
        int pid = NULL_PROCESS_ID;
        Field field;
        if (Platform.isWindows()) {
            try {
                field = process.getClass().getDeclaredField("handle");
                field.setAccessible(true);
                long handle = field.getLong(process);
                WinNT.HANDLE winntHandle = new WinNT.HANDLE();
                winntHandle.setPointer(Pointer.createConstant(handle));
                pid = Kernel32.INSTANCE.GetProcessId(winntHandle);
            } catch (Exception e) {
                LOGGER.error("获取进程id失败，异常信息：", e);
            }
        } else if (Platform.isLinux() || Platform.isAIX()) {
            try {
                field = process.getClass().getDeclaredField("pid");
                field.setAccessible(true);
                pid = field.getInt(process);
            } catch (Exception e) {
                LOGGER.error("获取进程id失败，异常信息：", e);
            }
        }
        LOGGER.info("进程id={}", pid);
        return pid;
    }

    /**
     * 终止进程
     * @param pid 进程的PID
     * @return true：成功，false：失败
     */
    public static boolean killProcessByPid(int pid) {
        if (NULL_PROCESS_ID == pid) {
            LOGGER.error("pid[{}]异常", pid);
            return false;
        }
        String command = "kill -9 " + pid;
        boolean result;
        if (Platform.isWindows()) {
            command = "cmd.exe /c taskkill /PID " + pid + " /F /T ";
        }
        Process process  = null;
        try {
            process = Runtime.getRuntime().exec(command);
        } catch (IOException e) {
            LOGGER.error("终止进程[pid={}]异常：", pid, e);
            return false;
        }
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
            //杀掉进程
            String line;
            while ((line = reader.readLine()) != null) {
                LOGGER.info(line);
            }
            result = true;
        } catch (Exception e) {
            LOGGER.error("终止进程[pid={}]异常：", pid, e);
            result = false;
        } finally {
            if (!Objects.isNull(process)) {
                process.destroy();
            }
        }
        return result;
    }

    /**
     * 获取进程信息
     * @param pid 进程id
     * @return 进程信息
     */
    public static OSProcess getProcessInfo(int pid) {
        SystemInfo systemInfo = new SystemInfo();
        OperatingSystem os = systemInfo.getOperatingSystem();
        return os.getProcess(pid);
    }
}